#!/usr/bin/python
# -*- encoding: utf8

import cmd
import readline
import os
import pwd, getpass

from cubemail import meta, model

class qbmCmd(cmd.Cmd):

    def __init__(self):
        cmd.Cmd.__init__(self)
        self.user=getpass.getuser()
        self.user_shell=pwd.getpwnam(self.user).pw_shell

        self.intro="""
        QB Mail admin tool, running as user '%s'
        DB: %s@%s
        """ % (self.user, meta.engine.url.database, meta.engine.url.host)

        self.domain=None
        self.user=None
        self.alias=None

        self.users=False
        self.aliases=False

        self.setprompt()

    @property
    def level(self):
        if self.domain == None:
            return "domains"

        if self.users:
            return "users"

        if self.aliases:
            return "aliases"

        if self.user != None:
            return "user"

        if self.alias != None:
            return "alias"

        if self.domain != None and (self.user == None and self.alias == None):
            return "domain"

    def setprompt(self, args=[]):
        if self.domain:
            dname=self.domain.name
        else:
            dname=''

        if self.level in ['users', 'aliases']:
            xname='/%s' % self.level
        else:
            xname=''

        if self.user:
            uname="/%s" % self.user.username
            xname='/users'
        else:
            uname=''

        if self.alias:
            aname="/%s" % self.alias
            xname='/aliases'
        else:
            aname=''

        self.prompt='%s%s%s%s> ' % (dname, xname, uname, aname)

    def selectdomain(self, args):
        r=meta.session.query(model.cmDomain).filter(model.cmDomain.name == args).first()
        if r:
            if r.isPrimary():
                self.domain=r
            else:
                self.domain=r.primary_domain
        else:
            print "no such domain"

    def selectuser(self, args):
        u=args.split('@')[0] # Process full username
        r=meta.session.query(model.cmUser).filter(model.cmUser.domain == self.domain).filter(model.cmUser.username==u).first()
        if r:
            self.user=r
            self.users=False
        else:
            print "no such user"

    def selectalias(self, args):
        lp=args.split('@')[0] # Process full alias
        r=meta.session.query(model.cmAlias).filter(model.cmAlias.domain == self.domain).filter(model.cmAlias.left_part==lp).first()
        if r:
            self.alias=r
            self.aliases=False
        else:
            print "no such alias"

    def star2percent(self, string):
        return string.replace('*', '%')

    def printdomains(self, args='*', longFormat=False):
        mask=self.star2percent(args)
        dl=meta.session.query(model.cmDomain).filter(model.cmDomain.name.like(mask)).all()
        for d in dl:
            if d.isPrimary():
                print " %s" % d.name
            else:
                print " %s -> %s" % (d.name, d.primary_domain)

    def printusers(self, args='%', longFormat=False):
        mask=self.star2percent(args)
        ul=meta.session.query(model.cmUser).filter(model.cmUser.domain==self.domain).filter(model.cmUser.username.like(mask)).all()
        if longFormat:
            print " %-20s %5s %4s" %  ('Username', 'UID', 'GID')
            print "-" * 32
        for u in ul:
            if longFormat:
                print " %-20s %5s %4s" % (u.fullusername, u.uid, u.gid)
            else:
                print " %s" % u.username

    def printaliases(self, args='%', longFormat=False):
        aliasDict={}
        mask=self.star2percent(args)
        al=meta.session.query(model.cmAlias).filter(model.cmAlias.domain==self.domain).filter(model.cmAlias.left_part.like(mask)).all()
        for a in al:
            if aliasDict.has_key(a.fullalias):
                aliasDict[a.fullalias].append(a.destination)
            else:
                aliasDict[a.fullalias]=[a.destination]

        for alias in aliasDict.keys():
            if longFormat:
                print " %s:" % alias
                print "\t%s" % ('\n\t'.join(aliasDict[alias]))
            else:
                print " %s" % (alias)

    # Customizations
    def emptyline(self):
        pass

    def postcmd(self, stop, line):
        self.setprompt()


    # Commands

    def do_EOF(self, args):
        print
        self.do_quit(args)

    def do_status(self, args):
        print "Domain: %s" % self.domain
        print "User: %s" % self.user
        print "Alias: %s" % self.alias
        print "Level: %s" % self.level

    def do_quit(self, args):
        """
        Exit without saving
        """
        print "Bye, bye"
        exit(0)

    def do_exit(self, args):
        """
        Exit, saving changes
        """
        print "Sayonara"
        exit(0)

    def do_shell(self, args):
        """
        Spawn a shell
        """
        print "Spawning shell %s, type 'exit' to return" % self.user_shell
        os.system(self.user_shell)

    def do_ls(self, args='*'):

        longFormat=False

        argArray=args.split(' ')
        if len(argArray) > 0:
            if argArray[0] == '-l':
                argArray.pop(0)
                longFormat=True
            args=' '.join(argArray)


        if not args: args='*'
        if self.level=="domains": self.printdomains(args, longFormat)
        if self.level=="domain": print "users/\naliases/"
        if self.level=="users": self.printusers(args, longFormat)
        if self.level=='aliases': self.printaliases(args, longFormat)
        if self.level=='user': print self.user
        if self.level=='alias': print self.alias

    def do_cd(self, args):
        if args=='..':
            if self.level=='domain': self.domain=None

            if self.level=='aliases':
                self.aliases=False
            if self.level=='users':
                self.users=False
            if self.level=='user':
                self.user=None
                self.users=True
            if self.level=='alias':
                self.alias=None
                self.aliases=True
            return

        if self.level in ['user', 'alias']:
            print "Cannot go lower to look for '%s'" % args
            return 

        if self.level=='domains':
            self.selectdomain(args)

        if self.level=='users':
            self.selectuser(args)

        if self.level=='aliases':
            self.selectalias(args)

        if self.level=='domain':
            if args=='users': self.users=True
            if args=='aliases': self.aliases=True

        
def main():
    c=qbmCmd()
    c.cmdloop(c.intro)

if __name__ == '__main__':
    main()

